#####################################################################
# File:         AssessmentCache.py
# Product:      KnowledgeEngine
#
# Copyright:    Copyright (c) 2001, Faulkner Ltd.
# Author:       Brian Oliver
#
# Description:  This file defines the AssessmentCache class,
#               for caching individual web assessment states for a model
#               in the Faulkner Knowledge Engine
#
# See Also:     Model
#####################################################################

#####################################################################
## KnowledgeEngine Library Imports
from Common import *

#####################################################################
## Zope Library Imports
# (none)
 
#####################################################################
## Python Library Imports
# (none)

#####################################################################
## AssessmentCache Class Definition
class AssessmentCache:
    """
        A transitent/volatile cache for an assessment for a model.
        Used to temporarily cache web assessment component state.
    """

    #---------------------------------------------------------------#

    def __init__(self, model, assessmentIdentity):
        "Constructor for the object"    
        
        self.identity = assessmentIdentity
        self.model = model
        self.statecache = {}
        self.scorecache = {}
        self.usercache = ''
        self.isModified = false
        self.isNew = false
        self.lockedcache = 'notset'

    #---------------------------------------------------------------#

    def getIdentity(self):
        """
            Returns the unique identity for the assessment
            RETURN TYPE: String
        """
        
        return self.identity

    #---------------------------------------------------------------#

    def getModel(self):
        """
            Returns the Model for the assessment.
            RETURN TYPE: Model Class            
        """
        
        return self.model
        
    #---------------------------------------------------------------#

    def getIsNew(self):
        """
            Returns if the assessment is new.
            RETURN TYPE: Boolean
        """            
        
        return self.isNew

    #---------------------------------------------------------------#

    def getIsModified(self):
        """
            Returns if the assessment is modified.
            RETURN TYPE: Boolean
        """            
        
        return self.isModified
            
    #---------------------------------------------------------------#

    def isLocked(self):
        """
            Returns if the assessment is locked.
            RETURN TYPE: Boolean
        """
        model=self.getModel()
        modelid=model.getIdentity()
        if self.lockedcache=='notset':
            user = self.getUser()
            if user != "unknown":
                uarules = model.getEnvironment().getUserAccessManager().getUserAccessRules(user.getUserName())
                self.lockedcache=uarules.isAssessmentLocked(modelid,self.getIdentity())
            else:
                self.lockedcache=1==0
        
        return self.lockedcache
            
    #---------------------------------------------------------------#

    def getState(self, componentIdentity, asHTML = false):
        """
            Returns the state of the specified component. If the
            component is not in the cache, it is looked up
            via the Model, and then stored in the cache.

            If the asHTML is true, the result is marked up as
            HTML prior to being returned. 

            NOTE: Returned value is a PYTHON value (not HTML)
        """
    
        #get the component
        component = self.getModel().getComponent(componentIdentity, true)

        #Warn if the specified component doesn't exist
        if component is None:
            print "[KnowledgeEngine.AssessmentCache.getState()] WARNING: Can't find component %s in model %s" % (componentIdentity, self.getModel().getIdentity())

        #check if the component state is in the cache
        if not self.statecache.has_key(componentIdentity):
            #not in the cache... find in model and put in cache
            self.statecache[componentIdentity] = component.getState(self.getModel(), self.getIdentity(), componentIdentity)

        #return the result as HTML?
        if asHTML:
            return toHTML(self.statecache[componentIdentity])
        else:            
            return self.statecache[componentIdentity]
            
    #---------------------------------------------------------------#

    def getScore(self, componentIdentity, asHTML = false):
        """
            Returns the score of the specified component. If the
            component is not in the cache, it is looked up
            via the Model, and then stored in the cache.

            If the asHTML is true, the result is marked up as
            HTML prior to being returned. 

            NOTE: Returned value is a PYTHON value (not HTML)
        """
    
        #get the component
        component = self.getModel().getComponent(componentIdentity)
        if not component.isInstanceOf("Scorable"):
            return None

        #check if the component score is in the cache
        if not self.scorecache.has_key(componentIdentity):
            #not in the cache... find in model and put in cache
            self.scorecache[componentIdentity] = component.getScore(self)

        #return the result as HTML?
        if asHTML:
            return toHTML(self.scorecache[componentIdentity])
        else:            
            return self.scorecache[componentIdentity]
            
    #---------------------------------------------------------------#

    def getUser(self, asHTML = false):
        """
            Returns the user instance that owns the specified assessment. 
            If the user is not in the cache, it is looked up
            and then stored in the cache.

            If the asHTML is true, the result is marked up as
            HTML prior to being returned. 

            NOTE: Returned value is the user object use getUserName() for the id.
        """
    
        #get the component
        model = self.getModel()

        #check if the user is in the cache
        if self.usercache=='':
            #not in the cache... find user and put in cache
            self.usercache = model.getEnvironment().getUserAccessManager().getUserByAssessmentId(self.getIdentity())

        #return the result as HTML?
        if asHTML:
            return toHTML(self.usercache)
        else:            
            return self.usercache
            
    #---------------------------------------------------------------#

    def getFullUserName(self):
        """
            Return the full user name so it can be displayed in things like reports
        """
        
        #get the user instance from this assessment cache
        user = self.getUser()
        
        #now use the acl_users to find out their exact name
        if user is not None and user != "unknown":
        
            #is the acl_users folder an extensible one (it supports getting the fullname and other attributes)
            if self.getModel().getEnvironment().getUserFolderType() == "exUserFolder":                
                
                exUserFolder = self.getModel().getEnvironment().getUserFolder()   
                
                #does the user have a realname?
                if user.hasProperty("realname") and user.getProperty("realname","") != "":
                    realName = user.getProperty("realname")
                else:    
                #try to get their firstname and lastname
                    firstName = user.getProperty("firstname", "")
                    lastName = user.getProperty("lastname", "")

                    if len(firstName) == 0 and len(lastName) == 0:
                        realName = "(Anonymous)"
                    else:
                        realName = "%s %s" % (firstName, lastName)

                return realName 
                                
            else:
                #as we're not using the exUserFolder, just return the normal username (user id)
                return user
        
        else:
            return "(Unknown)"
            
    #---------------------------------------------------------------#

    def getName(self):
        """
            Returns the name of the assessment for the user 
            or (anonymous) if the assessment is anonymous
        """

        #get the user instance from this assessment cache
        user = self.getUser()
        
        #now use the acl_users to find out the user id
        if user is not None and user != "unknown":
        
            return self.getModel().getEnvironment().getUserAccessManager().getUserAccessRules(user.getUserName()).getAssessmentName(self.getModel().getIdentity(), self.getIdentity())

        else:
            return "(Anonymous)"
            
    #---------------------------------------------------------------#

    def setState(self, componentIdentity, state):
        """
            Sets the state of the specified component.  This state
            is saved in the cache.  It is only made persistent
            (saved to disk) when the save() method is called.
        """

        #get the component
        component = self.getModel().getComponent(componentIdentity)
        
        #set the component state (with the correct type value)
        self.statecache[componentIdentity] = component.getTypedAssessmentValue(state)

        #the cache has been modified
        self.isModified = true
        
    #---------------------------------------------------------------#
    
    def setIsNew(self):
        """
            Sets that the assessment is actually new and modified
        """
        
        self.isNew = true
        self.isModified = true
        
    #---------------------------------------------------------------#

    def save(self):
        """
            Save the current entries in the cache to the database
        """

        #get the model
        model = self.getModel()

        #get the assessment identity
        identity = self.getIdentity()

        #we're only saving the state of the components in the cache
        for componentIdentity in self.statecache.keys():

            #get the component
            component = model.getComponent(componentIdentity)

            #save the state that's in the cache
            component.setState(model, identity, componentIdentity, self.statecache[componentIdentity])
            
    #---------------------------------------------------------------#

#####################################################################
## Class Initialisation
# (none)
